package exp;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import stat.GaussianModel;
import stat.Threshold;

public class NoiseFilter {

	private double x[];

	private double p[];

	private double threshold = 1e-2;

	private boolean showMsg = true;

	public NoiseFilter(double data[]) {
		x = data;
		initThreshold();
		initPower();
	}

	private void initPower() {
		p = new double[getData().length];
		for (int i = 0; i < p.length; i++)
			p[i] = ((double)1) / ((double)p.length);
	}

	public void setData(double data[]) {
		x = data;
		initThreshold();
		initPower();
	}

	private void initThreshold() {
		double min = getData()[0], max = getData()[0];
		for (int i = 1; i < getData().length; i++) {
			min = Math.min(min, getData()[i]);
			max = Math.max(max, getData()[i]);
		}

		threshold = Math.abs(max - min) * 0.01;
	}

	public double[] getData() {
		return x;
	}

	public double[] getPower() {
		return p;
	}

	public double[] getNormalizedData() {
		double nd[] = new double[getData().length];
		for (int i = 0; i < nd.length; i++) {
			nd[i] = getData()[i] * getPower()[i];
		}
		return nd;
	}

	public void setPower(double[] np) {
		p = new double[np.length];
		double sum = 0;
		for (int i = 0; i < np.length; i++) {
//			np[i] = np[i] * np[i];
			sum += np[i];
		}
		for (int i = 0; i < p.length; i++) {
			p[i] = np[i] / sum;
		}
	}

	public int[] recur(int k) {
		int[] index;

		double mean = GaussianModel.calcMean(getData());
		double var = GaussianModel.calcDev(getData());
		double ddd = mean + var;

//		double max = DoubleStat.max(getData());
//		if ()
		if (var < Threshold.thresholdOf(k))
			return new int[0];

		List<Integer> ints = new ArrayList<Integer>();
		for (int i = 0; i < getData().length; i++) {
			if (getData()[i] > ddd) {
				ints.add(i);
			}
		}

		index = new int[ints.size()];
		int ii = 0;
		for (Iterator<Integer> it = ints.iterator(); it.hasNext(); ) {
			index[ii++] = it.next();
		}
		return index;
	}

	public int[] recur2() {
		double prevVar = 0;
		double curVar = GaussianModel.calcDev(getData());;
		double[] data;
		int iii = 0;
		do {
			prevVar = curVar;
			if (showMsg)
			System.out.println("prevVar = " + curVar);
			data = getNormalizedData();
//			printDoubleArray("Norm Data", data);
			GaussianModel gm = new GaussianModel(data);
			double[] power = gm.calcValues(data);
			setPower(power);
			curVar = GaussianModel.calcDev(getNormalizedData());
			if (showMsg) {
				System.out.println("curVar = " + curVar);

				System.out.println("disVar with next = " + Math.abs(curVar - prevVar));
				System.out.println("------------------------------------------");
			}
			iii++;
		} while (Math.abs(curVar - prevVar) > threshold);
//		while (iii < 2);

		data = getNormalizedData();
//		int count = 0;
//		boolean is = false;
		double mean = GaussianModel.calcMean(data);
		double var = GaussianModel.calcDev(data);
		double ddd = mean + 3 * var;

		List<Integer> ints = new ArrayList<Integer>();
		for (int i = 0; i < data.length; i++) {
			if (data[i] > ddd) {
				ints.add(i);
			}
		}

		int[] index = new int[ints.size()];
		int ii = 0;
		for (Iterator<Integer> it = ints.iterator(); it.hasNext(); ) {
			index[ii++] = it.next();
		}
		return index;
//		for (int i = 0; i < data.length; i++) {
//			if (data[i] > ddd) {
//				if (showMsg)
//				System.out.println("| index of " + i + " : " + getData()[i]);
//				if (!is) {
//					count ++;
//					is = true;
//				}
//			} else {
//				is = false;
//			}
//		}
//		System.out.println("noise count = " + count);
	}

	public static void printDoubleArray(String msg, double[] d) {
		System.out.print(msg + ": ");
		for (double dd : d) {
			System.out.print(dd + " ");
		}
		System.out.println("\n");
	}

	public static void printIntArray(String msg, int[] n) {
		System.out.print(msg + "");
		for (int i : n) {
			System.out.println(i + " ");
		}
		System.out.println("\n");
	}

}
